Skip to content

Conversation

@Nazarevsky
Copy link
Collaborator

@Nazarevsky Nazarevsky commented Dec 12, 2025

Resolves #8514

Problem

xpay RPC call sends funds using Bolt11 or Bolt12 invoices provided. According to Bolt12, Bolt12 invoices support providing descriptions for invoices ('description' field) and messages to a payee on an invoice layer ('invreq_payer_note' field).

xpay has a couple of RPC calls (like fetchinvoice or create_invoice) under the hood which already have a corresponding logic for sending a custom message to a payee (using payer_note field). However, xpay does not have a field to provide payment description.

Changes

  • added payer_note filed to xpay RPC call;
  • updated schema;
  • added test case with payer_note defined.

Important

26.04 FREEZE March 11th: Non-bugfix PRs not ready by this date will wait for 26.06.

RC1 is scheduled on March 23rd

The final release is scheduled for April 15th.

Checklist

Before submitting the PR, ensure the following tasks are completed. If an item is not applicable to your PR, please mark it as checked:

  • The changelog has been updated in the relevant commit(s) according to the guidelines.
  • Tests have been added or modified to reflect the changes.
  • Documentation has been reviewed and updated as needed.
  • Related issues have been listed and linked, including any that this PR closes.
  • Important All PRs must consider how to reverse any persistent changes for tools/lightning-downgrade

@Nazarevsky Nazarevsky requested a review from cdecker as a code owner December 12, 2025 16:35
@Nazarevsky Nazarevsky marked this pull request as draft December 12, 2025 16:35
@Nazarevsky Nazarevsky force-pushed the feature/xpay-payment-description branch from 219da3a to c15a836 Compare December 15, 2025 10:16
@Nazarevsky Nazarevsky self-assigned this Dec 15, 2025
@Nazarevsky Nazarevsky marked this pull request as ready for review December 15, 2025 13:41
@Nazarevsky Nazarevsky force-pushed the feature/xpay-payment-description branch 2 times, most recently from 644563e to 51e5ed7 Compare December 15, 2025 14:06
@ShahanaFarooqui ShahanaFarooqui self-requested a review December 15, 2025 21:04
@ShahanaFarooqui ShahanaFarooqui added this to the 26.06 milestone Dec 15, 2025
Copy link
Collaborator

@ShahanaFarooqui ShahanaFarooqui left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Nazarevsky Thanks for the PR! Since this is your first contribution, I’m being a bit more nitpicky about commit structure. Even if this one doesn’t end up being merged for the reason below, this review should be useful as a reference for future PRs.

That said, I wanted to better understand whether this PR serves its intended purpose. Don’t the existing invoice.description and fetchinvoice.payer_note already cover this use case? A node can already inspect these via listinvoices. How is the payer_note sent via xpay received on the other node? Adding @Lagrang3 in case I’ve missed anything.

@Nazarevsky
Copy link
Collaborator Author

@Nazarevsky Thanks for the PR! Since this is your first contribution, I’m being a bit more nitpicky about commit structure. Even if this one doesn’t end up being merged for the reason below, this review should be useful as a reference for future PRs.

That said, I wanted to better understand whether this PR serves its intended purpose. Don’t the existing invoice.description and fetchinvoice.payer_note already cover this use case? A node can already inspect these via listinvoices. How is the payer_note sent via xpay received on the other node? Adding @Lagrang3 in case I’ve missed anything.

Thank you @ShahanaFarooqui for comments!

I've updated my PR description a bit about my changes. Nevertheless, I'd like to answer your questions here.

I think that invoice.description is a bit different because it provides a message to a payer. Basically, I'd say that it is rather an invoice description then payment description unlike payer_note. As you mentioned, fetchinvoice.payer_note is indeed exists and a corresponding logic for sending payer_note is implemented. However, no corresponding field in xpay for sending custom messages provided.

@ShahanaFarooqui
Copy link
Collaborator

ShahanaFarooqui commented Dec 16, 2025

I think that invoice.description is a bit different because it provides a message to a payer. Basically, I'd say that it is rather an invoice description then payment description unlike payer_note. As you mentioned, fetchinvoice.payer_note is indeed exists and a corresponding logic for sending payer_note is implemented. However, no corresponding field in xpay for sending custom messages provided.

Why a sender cannot attach an arbitrary description to a Lightning payment:

BOLT 4 (Onion Routing Protocol) defines the Lightning payment routing layer and specifies exactly what data is carried hop-by-hop in a payment.

According to BOLT 4:

  • Onion payloads carry routing and settlement data only, such as: amounts, CLTV expiry values, channel identifiers, defined TLV records required for forwarding
  • A payment is identified solely by the payment hash/preimage
  • There is no field for a free-form sender description or payer note
    As a result, the sender cannot arbitrarily attach descriptive metadata at the routing or payment layer.

By contrast, descriptions are defined only at the invoice layer:

BOLT 11 invoices include a d (description) or h (description hash) field, set by the invoice creator (receiver)
BOLT 12 similarly defines descriptions as part of offers/invoices (again receiver-defined)

Summary

  • The Lightning protocol does not support it
  • Lightning allows descriptions only in invoices (bolt11/botl12), which are created by the receiver.
  • The routing and payment protocol (BOLT 4) provides no mechanism for a sender to attach an independent description to a payment.

@Nazarevsky
Copy link
Collaborator Author

Nazarevsky commented Dec 17, 2025

Thank you for referencing, it makes much more sense to me now 👍

@cdecker
Copy link
Member

cdecker commented Dec 17, 2025

Thanks for the PR @Nazarevsky, I may be missing the purpose of it. There are plenty of places in both CLN and the spec where a description of some sort is mentioned.

As far as I see we only have XXX times that a description leaves one node and ends up at another node:

  • fetchinvoice where the payer_note, which I think, which is handled by the offers plugin. During the negotiation for a BOLT12 invoice, the prospective sender sends the recipient some metadata, to retrieve the invoice, and passing a note along. This is not saved as far as I see. This is not equivalent to calling xpay since it happens during the negotiation of the invoice, not the payment attempt of the invoice.
  • create_invoice is purely local, and the description is added to the invoice being returned, and not saved. Since there is no communication involved this is not comparable.
  • As part of the invoice we also pass a description along in the invoice, as an encoded base58 string.

I'm not against sending an optional message along with the payment, however notice that the spec does not have a field to transport this message, and the recipient has no handling / storing of any received message. If we want to go down this road, we should at least remember the messages we get ourselves first :-)

Anyway, as mentioned, I may be completely off, so please share your intent and we can work off of that ^^

EDIT: reading the OP again, it seems clear that there is a bit of confusion what the scope is. BOLT11 is the payment descriptor in the form of an invoice, i.e., they are the payment instructions sent from recipient to the sender on how to get back to it.

BOLT12 takes a step back, we don't have an invoice yet, we need to negotiate one. The prospective sender, given the recipient ID, talks to it, providing all the details for the payment it intends to perform. The recipient takes that information and returns an invoice.

So BOLT12 tells you how to get an invoice, BOLT11 tells you what is in the invoice, and xpay, renepay and pay take an invoice and execute the payment.

@Nazarevsky
Copy link
Collaborator Author

Thank you for joining @cdecker!

so please share your intent and we can work off of that

Basically, my intent was to provide some custom message using xpay command. As it was mentioned, it is not possible to do it by providing along with a payment directly, so I decided to do it by payer_note field in fetchinvoice RPC call (according to Bolt12 specification, type 89).

Current implementation already has payer_note field in fetchinvoice RPC call. On the other side even though xpay leverages fetchinvoice, xpay has no logic for providing a custom message even on an invoice later, so adding this field to the JSON request did all the work.

If we want to go down this road, we should at least remember the messages we get ourselves first

I also think so. listinvoices shows us payer_note for BOLT12 invoices so I decided to not add any other methods for that. Do you think that we need the other approach for getting messages?

So BOLT12 tells you how to get an invoice, BOLT11 tells you what is in the invoice, and xpay, renepay and pay take an invoice and execute the payment.

Yes, since there is no way to provide payment description when paying BOLT11 invoices, I decided to leave it as it is.

@cdecker
Copy link
Member

cdecker commented Dec 18, 2025

My bad, I totally blanked on the fact that xpay does use fetchinvoice to actually execute BOLT12, which does have the payer_note, and it is already being handled correctly by the offers plugin. Apologies for not realizing my mistake earlier, your PR makes absolute sense now.

I think this is good as is, and can be merged 👍

@Nazarevsky Nazarevsky force-pushed the feature/xpay-payment-description branch from 3bd4374 to 5c691d7 Compare December 18, 2025 16:31
@Nazarevsky Nazarevsky force-pushed the feature/xpay-payment-description branch from 5c691d7 to faff902 Compare December 18, 2025 16:48
@Nazarevsky Nazarevsky changed the title Feature/xpay payment description xpay: payment description Dec 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

give xpay the possibility to send a message to the payee

3 participants